#include "Datas.hpp"
#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

/// Stream operator
std::ostream& operator<<(
	std::ostream& o, const Datas::shipinfo_t& i)
{
	o << static_cast<int>(i.type)
		<< ": " << i.name << endl
		<< "\tLife:" << i.life << endl
		<< "\tMd:" << i.movable_distance << endl
		<< "\tAd:" << i.attackable_distance << endl
		<< "\tS : o=" << i.sight_over
		<< ", u=" << i.sight_under << endl
		<< "\tS : d=" << i.sight_depth
		<< ", uw=" << i.sight_underwater
		<< endl;
	return o;
}

/*
std::ostream& operator<<(
	std::ostream& o, const equipinfo_t& i)
{
	o << endl << "<Equip Datas>" << endl;
	o << i.name << endl;
}*/

namespace
{
	template<class T>
	struct printfunc
	{
		void operator()(const T& t)
		{
			cout << t;
		}
	};

	// print T
	template<class T>
	void print(const T* b, uint n)
	{
		for_each(b, b + n, printfunc<T>());
	}
	
	// get static array size
	template<class T, int N>
	int GetSizeOfArray(T (&)[N])
	{
		return N;
	}

	
	/**
	* @var shipinfo_t::op_flag
	*
	* This variable must specify enumed operation's alias.
	* @par Example
	* @code
	* op_flag = M | A | D;
	* @endcode
	*/
	// aliases for op_flag
	enum {
		M = 1,
		A = 2,
		D = 4,
		S = 8};
}

////////////////////////////////////////////////////////////////
// Data defination
//
/// Embedded data definations
namespace Datas
{
	/**
	* @brief Infomation of ship
	* @hideinitializer
	*
	* * op_flag
	*	specify to allow enumed operations that are ored there
	*	@warning enum must match with @ref Operations 
	*/
	extern const shipinfo_t ShipInfos[] = 
	{
		{
			"DestroyerShip",1,
			MobTypes::Ship,
			M | A | S,
			3, 3, 4, 1, 1, 0
		},
		{
			"BattleShip",2,
			MobTypes::Ship,
			M | A,
			2, 4, 5, 2, 1, 0
		},
		{
			"Submarine",1,
			MobTypes::Submarine,
			M | A | D,
			1, 2, 3, 2, 2, 2
		},
		{
			"Transporter",1,
			MobTypes::Ship,
			M,
			1, 1, 1, 1, 1, 1
		}

		// ... and more.
	};
	
	/// Size of Shipinfos
	uint GetShipInfosSize()
	{
		return GetSizeOfArray(ShipInfos);
	}

	/// Get num of turns to be diving.
	uint GetDivingCount()
	{
		return 3;
	}

/*
	equipinfo_t Equipment[] = 
	{
		{"test"}
		// and more...
	};
*/

	/// Print all embedded infomation
	void printall()
	{
		print(ShipInfos, GetShipInfosSize());
	//	print(Equipment, Equipment+1);
	}
}

